﻿#pragma
#ifndef FFMPEG_UTILS_H
#define FFMPEG_UTILS_H
#include <QDebug>

extern "C"
{
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/avutil.h"
}

/// <summary>
/// FFmpeg工具类
/// </summary>
class FFmpegUtils {
public:
	/// <summary>
	/// 获取YUV420P AVFrame
	/// </summary>
	/// <param name="width">视频宽度</param>
	/// <param name="height">视频高度</param>
	/// <param name="yData">Y数据</param>
	/// <param name="uData">U数据</param>
	/// <param name="vData">V数据</param>
	/// <returns></returns>
	AVFrame* GetFrame(int width, int height, uint8_t* yData, uint8_t* uData, uint8_t* vData)
	{
		AVFrame* frame = av_frame_alloc();
		frame->width = width;
		frame->height = height;
		frame->format = AV_PIX_FMT_YUV420P;//设置像素格式
		//设置linesize
		frame->linesize[0] = width;
		frame->linesize[1] = width / 2;
		frame->linesize[2] = width / 2;
		//生成图像空间,默认32字节对齐
		int ret = av_frame_get_buffer(frame, 0);
		outputErrorMsg(ret, "AVFrame生成图像空间");

		frame->data[0] = yData;
		frame->data[1] = uData;
		frame->data[2] = vData;
		return frame;
	}

	/// <summary>
	/// 获取YUV420P AVFrame
	/// </summary>
	/// <param name="width">视频宽度</param>
	/// <param name="height">视频高度</param>
	/// <param name="data">视频数据</param>
	/// <returns></returns>
	AVFrame* GetFrame(int width, int height, uint8_t* data)
	{
		AVFrame* frame = av_frame_alloc();
		frame->width = width;
		frame->height = height;
		frame->format = AV_PIX_FMT_YUV420P;//设置像素格式
		//设置linesize
		frame->linesize[0] = width;
		frame->linesize[1] = width / 2;
		frame->linesize[2] = width / 2;
		//生成图像空间,默认32字节对齐
		int ret = av_frame_get_buffer(frame, 0);
		outputErrorMsg(ret, "AVFrame生成图像空间");

		const int y_size = width * height;
		const int uv_size = (width / 2) * (height / 2);
		frame->data[0] = data;
		frame->data[1] = data + y_size;
		frame->data[2] = data + y_size + uv_size;
		return frame;
	}

	/// <summary>
	/// 销毁
	/// </summary>
	void Release()
	{
		/*av_frame_ref();
		av_frame_unref();
		av_frame_free();*/
	}
	/// <summary>
	/// 输出FFMpeg错误信息
	/// </summary>
	/// <param name="ret">错误号</param>
	/// <param name="errMsg">自定义错误前缀tips</param>
	void outputErrorMsg(int ret, QString errMsg) {
		if (ret != 0)
		{
			char buf[1024] = { 0 };
			av_strerror(ret, buf, sizeof(buf));
			qDebug() << errMsg << ",失败！->:" << buf;
		}
	}

	static FFmpegUtils* Get()
	{
		static FFmpegUtils fu;
		return &fu;
	}

};
#endif